/*
 * Copyright (c) 2022, IMMORTA Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * - Neither the name of IMMORTA Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef IPWM_DRV_H
#define IPWM_DRV_H

/*!
 * @file ipwm_drv.h
 * @brief This file declares ipwm driver interfaces
 */

/*!
 * @addtogroup ipwm_drv
 * @{
 */

/*******Includes***************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include "stdio.h"
#include "errcodes.h"
#include "device_registers.h"

/*******Definitions************************************************************/
/*!
 * @brief IPWM interrupt status structure
 */
typedef struct {
    uint8_t overflowStatus;    /*!< Overflow flag */
    uint8_t underflowStatus;   /*!< Underflow flag */
    uint8_t channelStatus;     /*!< Channel status */
#if (CONFIG_IPWM_SUPPORT_PHASEZ_INT == 1U)
    uint8_t phaseZStatus;      /*!< Phase z event status */
#endif
} ipwm_int_state_t;

/*!
 * @brief Callback for all peripherals which support IPWM features
 */
typedef void (*ipwm_callback_t)(uint32_t instance, void* param);

/*!
 * @brief IPWM channel enumeration
 */
typedef enum {
    IPWM_CH_0 = 0U,     /*!< PWM channel 0 */
    IPWM_CH_1 = 1U,     /*!< PWM channel 1 */
    IPWM_CH_2 = 2U,     /*!< PWM channel 2 */
    IPWM_CH_3 = 3U,     /*!< PWM channel 3 */
    IPWM_CH_MAX = 4U    /*!< Invalid channel */
} ipwm_channel_t;

/*!
 * @brief IPWM counting mode enumeration
 */
typedef enum {
    IPWM_UP_COUNT = 0U,         /*!< Up counting mode */
    IPWM_UP_DOWN_COUNT = 1U     /*!< Up-down counting mode */
} ipwm_count_mode_t;

/*!
 * @brief IPWM channel output active polarity enumeration
 */
typedef enum {
    IPWM_OUTPUT_POLARITY_ACTIVE_HIGH = 0U,   /*!< The channel output polarity is active high */
    IPWM_OUTPUT_POLARITY_ACTIVE_LOW = 1U     /*!< The channel output polarity is active low */
} ipwm_active_output_polarity_t;

/*!
 * @brief IPWM output level enumeration
 */
typedef enum {
    IPWM_LOW_LEVEL = 0U,        /*!< Low LEVEL */
    IPWM_HIGH_LEVEL = 1U        /*!< High LEVEL */
} ipwm_output_level_t;

/*!
 * @brief IPWM input edge enumeration
 */
typedef enum {
    IPWM_FALLING_EDGE = 0U,       /*!< Falling LEVEL */
    IPWM_RISING_EDGE = 1U         /*!< Rising LEVEL */
} ipwm_input_edge_t;

/*!
 * @brief IPWM channel event ratio enumeration
 */
typedef enum {
    IPWM_CH_EVENT_RATIO_1 = 0U,         /*!< Channel event ratio is 1 */
    IPWM_CH_EVENT_RATIO_2 = 1U,         /*!< Channel event ratio is 2 */
    IPWM_CH_EVENT_RATIO_4 = 2U,         /*!< Channel event ratio is 4 */
    IPWM_CH_EVENT_RATIO_8 = 3U          /*!< Channel event ratio is 8 */
} ipwm_ch_event_ratio_t;

/*!
 * @brief IPWM channel match point in combine mode enumeration
 */
typedef enum {
    IPWM_MATCH_DIR_DOWN = 0U,       /*!< Channel match point in down counting direction */
    IPWM_MATCH_DIR_UP = 1U          /*!< Channel match point in up counting direction */
} ipwm_match_dir_t;

/*!
 * @brief IPWM channel work mode enumeration
 */
typedef enum {
    IPWM_DUAL_EDGE_CAPTURE_CONTINOUS_MODE = 0U,         /*!< Dual edge capture continous mode */
    IPWM_DUAL_EDGE_CAPTURE_ONE_SHOT_MODE = 1U,          /*!< Dual edge capture one-shot mode */
    IPWM_COMBINE_OUTPUT_CONTINOUS_MODE = 2U,            /*!< Combine output continous mode */
    IPWM_COMBINE_OUTPUT_ONE_SHOT_MODE = 3U              /*!< Combine output one-shot mode */
} ipwm_channel_mode_t;

/*!
 * @brief IPWM output mode enumeration
 */
typedef enum {
    IPWM_OUTPUT_HIGH_TRUE = 0U,         /*!< Output is high true */
    IPWM_OUTPUT_LOW_TRUE = 1U           /*!< Output is low true */
} ipwm_output_mode_t;

/*!
 * @brief IPWM input filter prescaler enumeration
 */
typedef enum {
    IPWM_INPUT_FILTER_PSC_1 = 0U,           /*!< 1 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_2 = 1U,           /*!< 2 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_4 = 2U,           /*!< 4 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_8 = 3U,           /*!< 8 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_16 = 4U,          /*!< 16 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_32 = 5U,          /*!< 32 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_64 = 6U,          /*!< 64 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_128 = 7U,         /*!< 128 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_256 = 8U,         /*!< 256 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_512 = 9U,         /*!< 512 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_1024 = 10U,       /*!< 1024 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_2048 = 11U,       /*!< 2048 event trigger input capture */
    IPWM_INPUT_FILTER_PSC_4096 = 12U        /*!< 4096 event trigger input capture */
} ipwm_input_filter_psc_t;

/*!
 * @brief IPWM dual edge capture enumeration
 */
typedef enum {
    IPWM_POSITIVE_PLUSE_WIDTH_CAPTURE = 0U,     /*!< Positive Pluse width capture */
    IPWM_NEGATIVE_PLUSE_WIDTH_CAPTURE = 1U,     /*!< Negative Pluse width capture */
    IPWM_RISING_EDGE_PERIOD_CAPTURE = 2U,       /*!< Period capture between two consecutive rising edges */
    IPWM_FALLING_EDGE_PERIOD_CAPTURE = 3U       /*!< Period capture between two consecutive falling edges */
} ipwm_dual_edge_capture_t;

/*!
 * @brief IPWM external trigger ratio enumeration
 */
typedef enum {
    IPWM_TRIGGER_RATIO_1 = 0U,      /*!< Trigger Ratio is 1 */
    IPWM_TRIGGER_RATIO_2 = 1U,      /*!< Trigger Ratio is 2 */
    IPWM_TRIGGER_RATIO_3 = 2U,      /*!< Trigger Ratio is 3 */
    IPWM_TRIGGER_RATIO_4 = 3U,      /*!< Trigger Ratio is 4 */
    IPWM_TRIGGER_RATIO_5 = 4U,      /*!< Trigger Ratio is 5 */
    IPWM_TRIGGER_RATIO_6 = 5U,      /*!< Trigger Ratio is 6 */
    IPWM_TRIGGER_RATIO_7 = 6U,      /*!< Trigger Ratio is 7 */
    IPWM_TRIGGER_RATIO_8 = 7U       /*!< Trigger Ratio is 8 */
} ipwm_trigger_ratio_t;

/*!
 * @brief IPWM quadrature decode mode enumeration
 */
typedef enum {
    IPWM_QUAD_PHASE_ENCODE = 0U,    /*!< Phase encoding mode */
    IPWM_QUAD_COUNT_DIR = 1U        /*!< Counter and direction encoding mode */
} ipwm_quad_decode_mode_t;

/*!
 * @brief IPWM quadrature decoder phase polarity enumeration
 */
typedef enum {
    IPWM_QUAD_PHASE_NORMAL = 0U,   /*!< Phase input signal polarity is not inverted */
    IPWM_QUAD_PHASE_INVERT = 1U    /*!< Phase input signal polarity is inverted */
} ipwm_quad_phase_polarity_t;

#if (CONFIG_IPWM_SUPPORT_DECODER_DIR == 1U)
/*!
 * @brief IPWM quadrature decoder direction enumeration
 */
typedef enum {
    IPWM_QUAD_DIR_DOWN = 0U,        /*!< Counter direction is down */
    IPWM_QUAD_DIR_UP = 1U           /*!< Counter direction is up */
} ipwm_quad_decode_dir_t;
#endif

/*!
 * @brief IPWM counter configuration structure
 */
typedef struct {
    uint8_t localClkPsc;            /*!< Local clock prescaler */
    uint8_t cntEn;                  /*!< Enable/Disable counter */
    uint16_t initValue;             /*!< Initial counter value */
    uint16_t modValue;              /*!< Maximum counter value */
    bool overflowIntEn;             /*!< Enable/Disable CNTOF interrupt */
    bool underflowIntEn;            /*!< Enable/Disable CNTUF interrupt */
    uint8_t cntOverflowFreq;        /*!< CNTOF frequency */
} ipwm_counter_config_t;

/*!
 * @brief IPWM quad counter configuration structure
 */
typedef struct {
    uint8_t cntEn;                  /*!< Enable/Disable counter */
    uint16_t initValue;             /*!< Initial counter value */
    uint16_t modValue;              /*!< Maximum counter value */
    bool overflowIntEn;             /*!< Enable/Disable CNTOF interrupt */
    bool underflowIntEn;            /*!< Enable/Disable CNTUF interrupt */
    uint8_t cntOverflowFreq;        /*!< CNTOF frequency */
} ipwm_quad_counter_config_t;

/*!
 * @brief IPWM combine channel configuration structure
 */
typedef struct {
    ipwm_channel_t channel;                         /*!< combine channel number */
    ipwm_counter_config_t counterConfig;            /*!< Counter config */
    ipwm_channel_mode_t mode;                       /*!< Channel work mode */
    ipwm_count_mode_t countMode;                    /*!< Counting mode */
    uint16_t cva;                                   /*!< Channel match value a */
    uint16_t cvb;                                   /*!< Channel match value b */
    bool minTriggerEn;                              /*!< Enable/Disable min trigger */
    bool maxTriggerEn;                              /*!< Enable/Disable max trigger */
    ipwm_output_mode_t eventaLevelMode;             /*!< Event a Output mode */
    ipwm_match_dir_t cvaMatchDir;                   /*!< CVa match dir */
    ipwm_match_dir_t cvbMatchDir;                   /*!< CVb match dir */
    ipwm_active_output_polarity_t chPolarity;       /*!< Channel active polarity */
    bool initOutputEn;                              /*!< Enable/Disable Initial Output */
    ipwm_output_level_t initLevel;                  /*!< Channel init output level */
    bool cvaMatchTriggerEn;                         /*!< Enable/Disable CVa match trigger */
    bool cvbMatchTriggerEn;                         /*!< Enable/Disable CVb match trigger */
    bool eventaIntEn;                               /*!< Enable/Disable channel event a interrupt */
    ipwm_ch_event_ratio_t eventaFreq;               /*!< CHFa Interrupt ratio */
    bool eventbIntEn;                               /*!< Enable/Disable channel event b interrupt */
    ipwm_ch_event_ratio_t eventbFreq;               /*!< CHFb Interrupt ratio */
} ipwm_combine_ch_config_t;

/*!
 * @brief IPWM combine output configuration structure
 */
typedef struct {
    uint8_t channelNum;                         /*!< Number of channels (0~3) */
    uint8_t globalPscVal;                       /*!< Global clk psc value */
    bool globalPscEn;                           /*!< Global clk psc enable */
    ipwm_combine_ch_config_t* combineChConfig;  /*!< Configuration for combine channels */
    ipwm_trigger_ratio_t triggerRatio;          /*!< External trigger ratio */
    bool intEn;                                 /*!< Enable/Disable NVIC irq */
#if (CONFIG_IPWM_UNIFIED_IRQ_FEATURE == 1U)
    ipwm_callback_t callBack;                   /*!< Interrupt callback pointer */
#else
    ipwm_callback_t channelCallBack;            /*!< Channel interrupt callback pointer */
    ipwm_callback_t overflowCallBack;           /*!< Overflow interrupt callback pointer */
#endif
} ipwm_combine_output_config_t;

/*!
 * @brief IPWM dual edge capture channel configuration structure
 */
typedef struct {
    ipwm_channel_t channel;                     /*!< Channel number */
    ipwm_counter_config_t counterConfig;        /*!< Counter config */
    ipwm_channel_mode_t mode;                   /*!< Channel work mode */
    ipwm_dual_edge_capture_t captureType;       /*!< Channel dual edge capture type */
    uint8_t chFilterValue;                      /*!< Channel filter value */
    bool eventaRst;                             /*!< Enable/Disable channel event a cnt reset */
    bool eventbRst;                             /*!< Enable/Disable channel event b cnt reset */
    bool eventaIntEn;                           /*!< Enable/Disable channel event a interrupt */
    ipwm_ch_event_ratio_t eventaFreq;           /*!< CHFa Interrupt ratio */
    bool eventbIntEn;                           /*!< Enable/Disable channel event b interrupt */
    ipwm_ch_event_ratio_t eventbFreq;           /*!< CHFb Interrupt ratio */
} ipwm_dual_edge_capture_ch_config_t;

/*!
 * @brief IPWM dual edge capture configuration structure
 */
typedef struct {
    uint8_t channelNum;                                 /*!< Number of dual edge capture channels */
    uint8_t globalPscVal;                               /*!< Global clk psc */
    uint8_t globalPscEn;                                /*!< Global clk psc enable */
    ipwm_dual_edge_capture_ch_config_t* channelConfig;  /*!< Input capture channels configuration */
    ipwm_input_filter_psc_t filterPsc;                  /*!< Input filter psc */
    bool hallEn;                                        /*!< Enable/Disable hall mode */
    bool intEn;                                         /*!< Enable/Disable NVIC irq */
#if (CONFIG_IPWM_UNIFIED_IRQ_FEATURE == 1U)
    ipwm_callback_t callBack;                           /*!< Interrupt callback pointer */
#else
    ipwm_callback_t channelCallBack;                    /*!< Channel interrupt callback pointer */
    ipwm_callback_t overflowCallBack;                   /*!< Overflow interrupt callback pointer */
#endif
} ipwm_dual_edge_capture_config_t;

/*!
 * @brief IPWM sync channel configuration structure
 */
typedef struct {
    ipwm_channel_t channel;                     /*!< Channel number */
    bool counterSyncEn;                         /*!< Enable/Disable MOD/CNTIN/CNV sync */
    bool maxLoadingPointEn;                     /*!< Enable/Disable maximum loading point */
    bool minLoadingPointEn;                     /*!< Enable/Disable minimum loading point */
    bool chSyncEn;                              /*!< Enable/Disable channel sync */
} ipwm_ch_sync_config_t;

/*!
 * @brief IPWM sync configuration structure
 */
typedef struct {
    uint8_t channelNum;                    /*!< Number of sync config channels */
    ipwm_ch_sync_config_t* syncConfig;      /*!< Configuration for channel's sync function */
} ipwm_sync_config_t;

/*!
 * @brief IPWM quadrature decoder phase configuration structure
 */
typedef struct {
    ipwm_quad_phase_polarity_t polarity;               /*!< Phase channel polarity */
    uint8_t filterValue;                               /*!< Phase channel filter value */
} ipwm_quad_phase_config_t;

/*!
 * @brief IPWM quadrature decoder configuration structure
 */
typedef struct {
    ipwm_quad_counter_config_t counterConfig;   /*!< Counter config */
    ipwm_quad_decode_mode_t mode;               /*!< Quad decoder mode */
    ipwm_input_filter_psc_t filterPsc;          /*!< Input filter psc */
    ipwm_quad_phase_polarity_t phaseAPol;       /*!< Phase A channel polarity */
    uint8_t phaseAfilterValue;                  /*!< Phase A channel filter value */
    ipwm_quad_phase_polarity_t phaseBPol;       /*!< Phase B channel polarity */
    uint8_t phaseBfilterValue;                  /*!< Phase B channel filter value */
    ipwm_quad_phase_polarity_t phaseZPol;       /*!< Phase Z channel polarity */
    uint8_t phaseZfilterValue;                  /*!< Phase Z channel filter value */
    bool phaseZRstEn;                           /*!< Enable/Disable phase Z event reset counter */
    bool quadEn;                                /*!< Enable/Disable quad decoder */
    bool intEn;                                 /*!< Enable/Disable NVIC irq */
#if (CONFIG_IPWM_UNIFIED_IRQ_FEATURE == 1U)
    ipwm_callback_t callBack;                   /*!< Interrupt callback pointer */
#else
    bool phaseZIntEn;                           /*!< Enable/Disable phase z evnet interrupt */
    ipwm_callback_t channelCallBack;            /*!< Channel interrupt callback pointer */
    ipwm_callback_t overflowCallBack;           /*!< Overflow interrupt callback pointer */
#endif
} ipwm_quad_decoder_config_t;

/*******APIs*******************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif

/*!
 * @brief Configure IPWM channel combination output
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] config: Configuration of the combine output
 * @return None
 */
void IPWM_InitCombineOutput(uint32_t instance, const ipwm_combine_output_config_t* const config);

/*!
 * @brief Configure IPWM channel dual edge capture
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] config: Configuration of the dual edge captue channel
 * @return None
 */
void IPWM_InitDualEdgeCapture(uint32_t instance, const ipwm_dual_edge_capture_config_t* config);

/*!
 * @brief Set the IPWM channel work mode
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] mode
 *            - 0: IPWM_DUAL_EDGE_CAPTURE_CONTINOUS_MODE
 *            - 1: IPWM_DUAL_EDGE_CAPTURE_ONE_SHOT_MODE
 *            - 2: IPWM_COMBINE_OUTPUT_CONTINOUS_MODE
 *            - 3: IPWM_COMBINE_OUTPUT_ONE_SHOT_MODE
 * @return None
 */
void IPWM_SetChannelMode(uint32_t instance, ipwm_channel_t channel, ipwm_channel_mode_t mode);

/*!
 * @brief Configure IPWM channel software output control
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] enable
 *            - true: Enable software output control
 *            - false: Disable software output control
 * @param[in] level
 *            - 0: IPWM_LOW_LEVEL
 *            - 1: IPWM_HIGH_LEVEL
 * @return None
 */
void IPWM_SetChannelSoftwareControl(uint32_t instance, ipwm_channel_t channel, bool enable, ipwm_output_level_t level);

/*!
 * @brief Configure IPWM channel output mask
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] enable
 *            - true: Enable output mask
 *            - false: Disable output mask
 * @return None
 */
void IPWM_SetChannelOutputMask(uint32_t instance, ipwm_channel_t channel, bool enable);

/*!
 * @brief Set IPWM Modulo dither value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] modDitherValue: modulo dither value
 * @return None
 */
void IPWM_SetModDither(uint32_t instance, ipwm_channel_t channel, uint8_t modDitherValue);

/*!
 * @brief Set the IPWM channel value dither value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] cvaDitherValue: channel value a dither value
 * @param[in] cvbDitherValue: channel value b dither value
 * @return None
 */
void IPWM_SetChDither(uint32_t instance, ipwm_channel_t channel, uint8_t cvaDitherValue, uint8_t cvbDitherValue);

/*!
 * @brief Set the IPWM counter initial value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] cntInitValue: Counter initial value
 * @return None
 */
void IPWM_SetCntInitVal(uint32_t instance, ipwm_channel_t channel, uint16_t cntInitValue);

/*!
 * @brief Set the IPWM channel value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] cva: channel value a
 * @param[in] cvb: channel value b
 * @return None
 */
void IPWM_SetChannelValue(uint32_t instance, ipwm_channel_t channel, uint16_t cva, uint16_t cvb);

/*!
 * @brief Set the IPWM counter modulo value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] modValue: Counter modulo value
 * @return None
 */
void IPWM_SetMod(uint32_t instance, ipwm_channel_t channel, uint16_t modValue);

/*!
 * @brief Set the IPWM counter value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] cntValue: Counter value
 * @return None
 */
void IPWM_SetCounter(uint32_t instance, ipwm_channel_t channel, uint16_t cntValue);

/*!
 * @brief Get the IPWM current counter value
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @return Current counter value
 */
uint16_t IPWM_GetCounter(uint32_t instance, ipwm_channel_t channel);

/*!
 * @brief Get the IPWM channel value a
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @return Channel value a
 */
uint16_t IPWM_GetCVa(uint32_t instance, ipwm_channel_t channel);

/*!
 * @brief Get the IPWM channel value b
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @return Channel value b
 */
uint16_t IPWM_GetCVb(uint32_t instance, ipwm_channel_t channel);

/*!
 * @brief Get the IPWM all channel level
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return All channel level
 */
uint8_t IPWM_GetChannelLevel(uint32_t instance);

#if (CONFIG_IPWM_SUPPORT_DECODER_DIR == 1U)
/*!
 * @brief Get the IPWM quad decoder direction
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return Quad decoder direction
 */
bool IPWM_GetQuadDecoderDir(uint32_t instance);
#endif
/*!
 * @brief Configure IPWM quad decoder function
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] config: Configuration of the quad decoder function
 * @return None
 */
void IPWM_InitQuadDecoderMode(uint32_t instance, const ipwm_quad_decoder_config_t* config);

/*!
 * @brief Enable/Disable the IPWM write protect
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable the write protect
 *            - false: Disable the write protect
 * @return None
 */
void IPWM_SetWriteProtect(uint32_t instance, bool enable);

/*!
 * @brief Configure IPWM register sync
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] config: Configuration of the sync function
 * @return None
 */
void IPWM_InitSyncContol(uint32_t instance, ipwm_sync_config_t* config);

/*!
 * @brief Set software trigger to sync register
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @return None
 */
void IPWM_SetSoftwareTriggerSync(uint32_t instance, ipwm_channel_t channel);

/*!
 * @brief Enable/Disable the IPWM counter
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] channel: IPWM channel(IPWM_CH0~3)
 * @param[in] clkEn
 *            - true: Enable counter
 *            - false: Disable counter
 * @return None
 */
void IPWM_SetCntEn(uint32_t instance, ipwm_channel_t channel, bool clkEn);

/*!
 * @brief Enable/Disable the PWM global prescaler
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] clkEn
 *            - true: Enable local prescaler
 *            - false: Disable local prescaler
 * @return None
 */
void IPWM_SetGlobalPscEn(uint32_t instance, bool clkEn);

/*!
 * @brief Enable/Disable IPWM global time base
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable global time base
 *            - false: Disable global time base
 * @return None
 */
void IPWM_SetGlobalTimeBaseEnable(uint32_t instance, bool enable);

/*!
 * @brief Enable/Disable IPWM global time base output
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @param[in] enable
 *            - true: Enable global time base output
 *            - false: Disable global time base output
 * @return None
 */
void IPWM_SetGlobalTimeBaseOutput(uint32_t instance, bool enable);

/*!
 * @brief Deinit IPWM
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return None
 */
void IPWM_Deinit(uint32_t instance);

#if (CONFIG_IPWM_UNIFIED_IRQ_FEATURE == 1U)
/*!
 * @brief IPWM IRQ handler process
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return None
 */
void IPWM_IRQHandlerProcess(uint32_t instance);
#else
/*!
 * @brief IPWM channel IRQ handler process
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return None
 */
void IPWM_Channel_IRQHandlerProcess(uint32_t instance);

/*!
 * @brief IPWM overflow IRQ handler process
 *
 * @param[in] instance: The IPWM peripheral instance number
 * @return None
 */
void IPWM_Overflow_IRQHandlerProcess(uint32_t instance);
#endif

#if defined(__cplusplus)
}
#endif

/*! @} */

#endif /* IPWM_DRV_H */

/*******EOF********************************************************************/

